--------------C'est La Vie-------------
A 4am crack                  2018-04-07
---------------------------------------

Name: C'est La Vie
Genre: arcade
Year: 1983
Publisher: Adventure International
Platform: Apple ][+ or later
Media: 5.25-inch disk
Sides: 1
OS: DOS 3.3
Similar cracks:
  #1563 The Kingdom of Facts

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  read error on first pass

Locksmith Fast Disk Backup
  unable to read any track

EDD 4 bit copy (no sync, no count)
  error on track $22, copy seeks back
  and forth between tracks forever

Copy ][+ nibble editor
  track $22 is weeeeeeeird, mostly #$FF
  and #$DD nibbles, like hundreds and
  hundreds of them in a row, and timing
  bits between each nibble

Disk Fixer
  ["O"] for INPUT/OUTPUT CONTROL, then
  CHECKSUM ENABLED = NO
  bootloader is standard DOS 3.3
  RWTS is standard except it ignores
    the data field epilogue
  T01,S09 -> startup program is "HELO"
    (with 1 "L")
  T11 -> DOS 3.3 disk catalog
  ["D"] for DIRECTORY MODE shows that
    "HELO" exists and mostly just BRUNs
    the binary file "CLV", which seems
    to be the entire game
  no way to read track $22 (no standard
  structure)

Why didn't any of my copies work?
  probably a runtime check on that
  weird track $22

Next steps:

  1. Find the runtime protection check
  2. Disable it
  3. Declare victory (*)

(*) go to the gym

                   ~

               Chapter 1
 In Which We Quickly Get To The Point


Passport makes short work of converting
the disk to a readable format.

                 --v--

READING FROM S6,D1
T00,S00 FOUND DOS 3.3 BOOTLOADER
USING DISK'S OWN RWTS
T22 FOUND NIBBLE COUNT PROTECTION TRACK
WRITING TO S5,D2
T02,S02 VOLUME NAME IS DISK VOLUME 254

THE DISK WAS COPIED SUCCESSFULLY, BUT
PASSPORT DID NOT APPLY ANY PATCHES.

              --^--

As expected, the copy that it produces
fares no better than my failed EDD bit
copy.

Booting from a DOS 3.3 system master, I
can CATALOG this non-working copy.

]CATALOG

DISK VOLUME 254

 I 002 APPLESOFT
 B 002 B0100
 B 131 CLV
 A 002 HELO

]LOAD HELO
]LIST

 10  PRINT "BRUN CLV"
 20  PRINT "NOMONCIO": PRINT "BRU
     N CLV"

]BLOAD CLV
]CALL -151

*AA72.AA73

*AA72.AA73      ; address of last BLOAD

AA72- 00 08

*800L

0800-   20 68 27    JSR   $2768

OK.

*2768L

2768-   20 00 26    JSR   $2600
276B-   20 00 20    JSR   $2000
276E-   A9 00       LDA   #$00
2770-   A0 02       LDY   #$02
2772-   60          RTS

OK.

*2600L

2600-   4C 04 26    JMP   $2604
2603-   60          RTS
2604-   20 57 27    JSR   $2757

OK.

*2757L

; seek to track 0
2757-   A9 00       LDA   #$00
2759-   8D F2 B7    STA   $B7F2
275C-   8D EC B7    STA   $B7EC
275F-   A9 B7       LDA   #$B7
2761-   A0 E8       LDY   #$E8
2763-   20 00 BD    JSR   $BD00
2766-   D8          CLD
2767-   60          RTS

Continuing from $2607...

; turn on drive motor manually
2607-   AE 03 26    LDX   $2603
260A-   9D 89 C0    STA   $C089,X

; wait for it to spin up
260D-   A9 FF       LDA   #$FF
260F-   20 AB FC    JSR   $FCAB

; seek to track $22
2612-   AE 03 26    LDX   $2603
2615-   A9 44       LDA   #$44
2617-   20 A0 B9    JSR   $B9A0
261A-   D8          CLD

; initialize counters
261B-   A9 00       LDA   #$00
261D-   85 F0       STA   $F0
261F-   85 F1       STA   $F1
2621-   85 F2       STA   $F2
2623-   85 F3       STA   $F3
2625-   85 F4       STA   $F4
2627-   85 F5       STA   $F5
2629-   85 F6       STA   $F6
262B-   85 F7       STA   $F7

; look for #$DD or #$FF nibble
262D-   A0 00       LDY   #$00
262F-   AE 03 26    LDX   $2603
2632-   BD 8E C0    LDA   $C08E,X
2635-   BD 8C C0    LDA   $C08C,X
2638-   10 FB       BPL   $2635
263A-   C9 FF       CMP   #$FF
263C-   F0 6A       BEQ   $26A8
263E-   C9 DD       CMP   #$DD
2640-   F0 08       BEQ   $264A
2642-   C8          INY
2643-   C0 14       CPY   #$14
2645-   90 EE       BCC   $2635
2647-   4C 42 27    JMP   $2742

There are three ways out of this loop.
Two of them are OK -- we find an #$FF
nibble and branch to $26A8, or we find
a #$DD nibble and branch to $264A. Or
we don't find either of those nibbles,
Y increments out of range, and we give
up and branch to $2742.

If we find a #$DD nibble first, we
continue to $264A:

; look for #$FF nibble
264A-   BD 8C C0    LDA   $C08C,X
264D-   10 FB       BPL   $264A

; branch forward once we find it
264F-   C9 FF       CMP   #$FF
2651-   F0 0F       BEQ   $2662

; count the non-#$FF nibbles
2653-   E6 F6       INC   $F6
2655-   D0 F3       BNE   $264A
2657-   E6 F7       INC   $F7
2659-   A5 F7       LDA   $F7

; give up if we've seen $1000 nibbles
; without finding #$FF
265B-   C9 10       CMP   #$10
265D-   90 EB       BCC   $264A
265F-   4C 42 27    JMP   $2742  ; bad!

; success path continues here (from the
; BEQ at $2651) --
; now look for non-#$FF nibble
2662-   BD 8C C0    LDA   $C08C,X
2665-   10 FB       BPL   $2662
2667-   C9 FF       CMP   #$FF
2669-   D0 0F       BNE   $267A

; and give up after $1000 wrong nibbles
266B-   E6 F0       INC   $F0
266D-   D0 F3       BNE   $2662
266F-   E6 F1       INC   $F1
2671-   A5 F1       LDA   $F1
2673-   C9 10       CMP   #$10
2675-   90 EB       BCC   $2662
2677-   4C 42 27    JMP   $2742  ; bad!

; if the first non-#$FF nibble is #$DD,
; that's good
267A-   C9 DD       CMP   #$DD
267C-   F0 07       BEQ   $2685

; otherwise try again (but eventually
; give up after $100 non-#$DD nibbles)
267E-   E6 F4       INC   $F4
2680-   D0 E0       BNE   $2662
2682-   4C 42 27    JMP   $2742  ; bad!

; execution continues here (from "BEQ"
; at $267C) --
; count #$DD nibbles (zero page $F2/3)
; but give up after $1000 of them,
; terminate on #$FF nibble, tolerate up
; to 256 other values (zero page $F5)
2685-   BD 8C C0    LDA   $C08C,X
2688-   10 FB       BPL   $2685
268A-   C9 DD       CMP   #$DD
268C-   F0 0B       BEQ   $2699
268E-   C9 FF       CMP   #$FF
2690-   F0 74       BEQ   $2706  ; good
2692-   E6 F5       INC   $F5
2694-   D0 EF       BNE   $2685
2696-   4C 42 27    JMP   $2742
2699-   E6 F2       INC   $F2
269B-   D0 E8       BNE   $2685
269D-   E6 F3       INC   $F3
269F-   A5 F3       LDA   $F3
26A1-   C9 10       CMP   #$10
26A3-   90 E0       BCC   $2685
26A5-   4C 42 27    JMP   $2742  ; bad!

This path continues at $2706. This next
line is the start of the other major
path, from the "BEQ" at $263C, if we
initially found an #$FF nibble instead
of #$DD. (Tracks are just endless
circles, and there's no way to know
where in the circle we'll start. Rather
than burn through half the track
looking for one or the other, this
protection check is optimized to start
counting either way.)

                   ~

               Chapter 2
   In Which We Enter The Upside Down


This path is just the inverse of the
other path. Everything that was #$FF is
now #$DD, and vice versa.

; look for #$DD nibble
26A8-   BD 8C C0    LDA   $C08C,X
26AB-   10 FB       BPL   $26A8
26AD-   C9 DD       CMP   #$DD
26AF-   F0 0F       BEQ   $26C0

; count the non-#$DD nibbles, give up
; after $1000 non-#$DD nibbles
26B1-   E6 F6       INC   $F6
26B3-   D0 F3       BNE   $26A8
26B5-   E6 F7       INC   $F7
26B7-   A5 F7       LDA   $F7
26B9-   C9 10       CMP   #$10
26BB-   90 EB       BCC   $26A8
26BD-   4C 42 27    JMP   $2742  ; bad!

; execution continues here (from "BEQ"
; at $26AF) --
; now look for non-#$DD nibble
26C0-   BD 8C C0    LDA   $C08C,X
26C3-   10 FB       BPL   $26C0
26C5-   C9 DD       CMP   #$DD
26C7-   D0 0F       BNE   $26D8

; count the #$DD nibbles, give up after
; $1000 nibbles
26C9-   E6 F2       INC   $F2
26CB-   D0 F3       BNE   $26C0
26CD-   E6 F3       INC   $F3
26CF-   A5 F3       LDA   $F3
26D1-   C9 10       CMP   #$10
26D3-   90 EB       BCC   $26C0
26D5-   4C 42 27    JMP   $2742  ; bad!

; if the first non-#$DD nibble is #$FF,
; that's good
26D8-   C9 FF       CMP   #$FF
26DA-   F0 07       BEQ   $26E3

; otherwise try again (but eventually
; give up after $100 non-#$FF nibbles)
26DC-   E6 F5       INC   $F5
26DE-   D0 E0       BNE   $26C0
26E0-   4C 42 27    JMP   $2742  ; bad!

; execution continues here (from "BEQ"
; at $26DA) --
; count #$FF nibbles (zero page $F0/1)
; but give up after $1000 of them,
; terminate on #$DD nibble, tolerate up
; to $100 other nibbles (zero page $F4)
26E3-   BD 8C C0    LDA   $C08C,X
26E6-   10 FB       BPL   $26E3
26E8-   C9 FF       CMP   #$FF
26EA-   F0 0B       BEQ   $26F7
26EC-   C9 DD       CMP   #$DD
26EE-   F0 16       BEQ   $2706  ; good
26F0-   E6 F4       INC   $F4
26F2-   D0 EF       BNE   $26E3
26F4-   4C 42 27    JMP   $2742
26F7-   E6 F0       INC   $F0
26F9-   D0 E8       BNE   $26E3
26FB-   E6 F1       INC   $F1
26FD-   A5 F1       LDA   $F1
26FF-   C9 10       CMP   #$10
2701-   90 E0       BCC   $26E3
2703-   4C 42 27    JMP   $2742  ; bad!

; execution continues here (from "BEQ"
; at $26EE) --
; if we found too many of either nibble
; then the protection check has failed
2706-   A5 F4       LDA   $F4
2708-   C9 10       CMP   #$10
270A-   B0 36       BCS   $2742
270C-   A5 F5       LDA   $F5
270E-   C9 10       CMP   #$10
2710-   B0 30       BCS   $2742

; count of #$FF nibbles needs to be
; between #$0E68 and #$0E9C
2712-   A5 F1       LDA   $F1
2714-   C9 0E       CMP   #$0E
2716-   D0 2A       BNE   $2742
2718-   A5 F0       LDA   $F0
271A-   C9 68       CMP   #$68
271C-   90 24       BCC   $2742
271E-   C9 9C       CMP   #$9C
2720-   B0 20       BCS   $2742

; count of #$DD nibbles needs to be
; between #$0568 and #$059C
2722-   A5 F3       LDA   $F3
2724-   C9 05       CMP   #$05
2726-   D0 1A       BNE   $2742
2728-   A5 F2       LDA   $F2
272A-   C9 68       CMP   #$68
272C-   90 14       BCC   $2742
272E-   C9 9C       CMP   #$9C
2730-   B0 10       BCS   $2742

; Success! All nibble counts were
; within acceptable ranges. Now seek
; back to track 0, turn off the drive
; motor, and return to the caller.
2732-   AE 03 26    LDX   $2603
2735-   A9 00       LDA   #$00
2737-   20 A0 B9    JSR   $B9A0
273A-   D8          CLD
273B-   AE 03 26    LDX   $2603
273E-   BD 88 C0    LDA   $C088,X
2741-   60          RTS

; All failures lead here. Seek back to
; track 0, then track $22, and start
; over.
2742-   AE 03 26    LDX   $2603
2745-   A9 00       LDA   #$00
2747-   20 A0 B9    JSR   $B9A0
274A-   D8          CLD
274B-   A9 44       LDA   #$44
274D-   AE 03 26    LDX   $2603
2750-   20 A0 B9    JSR   $B9A0
2753-   D8          CLD
2754-   4C 1B 26    JMP   $261B

There are no side effects to this
protection check. If it fails, it tries
forever. If it succeeds, it restores
all state before returning to the
caller. It doesn't even set or clear
the carry flag.

I can bypass it by changing the JMP at
$2600 to "RTS".

T1F,S00,$04: 4C -> 60

]PR#6
...works, and it is glorious...

Quod erat liberand one more thing...

                   ~

               Chapter 3
    I Mean, It's One Bit, Michael.
   What Could It Cost? Ten Dollars?


The sequence of bits on track $22 is
very specific. It was designed to fool
the best bit copiers, and it does. But
why? How does it work? Why can't bit
copiers duplicate it?

This game was published by Adventure
International, better known for its
Scott Adams adventure games, and it
shares the protection bitstream with
those famous adventures. The earliest
sample in my collection is "Graphic
Adventure #1; Adventureland," dated
1982, but the protection may date back
even further.

That's a long time to reuse a copy
protection. Heck, six months was a long
time to reuse a copy protection. This
one is obviously durable.

Here is the original disk, as seen
through the Copy II Plus nibble editor.
(The editor indicates timing bits after
a nibble with inverse. I've displayed
them here as "+" signs.)

                 --v--

   COPY ][ PLUS BIT COPY PROGRAM 8.4
(C) 1982-9 CENTRAL POINT SOFTWARE, INC.
---------------------------------------

TRACK: 22  START: 1800  LENGTH: 3DFF

1CB0: DD+DD+DD+DD+DD+DD+DD+DD+
1CB8: FF 9F E7 F9 FE+FF+FF+FF+
1CC0: FF+FF+FF+FF+FF+FF+FF+FF+
...
2B30: FF+FF+FF+FF+FF+FF+FF+FF+
2B38: FF+FF+FF+FF+FF+FF+E9 BA+
2B40: DD+DD+DD+DD+DD+DD+DD+DD+
...
30B0: DD+DD+DD+DD+DD+DD+DD+DD+
30B8: DD+DD+DD+DD+DD+DD+FF 9F
30C0: E7 F9 FE+FF+FF+FF+FF+FF+

                 --^--

The offsets ($1CB0, $2B30, $30B0) are
not important here; in fact, they will
vary on every read. There's no defined
"start" to a track; it's an unending
circle of bits. The offsets depend on
the physical rotation of the disk when
Copy II Plus started reading. It's the
nibble counts that matter. That's what
the protection check cares about.

  - $DD (repeated $057E times)
  - $FF $9F $E7 $F9 $FE
  - $FF (repeated $0E81 times)
  - $E9 $BA

And, as indicated, there are timing
bits between most nibbles. But that's
it; in this view, the $9F nibble at
offset $1CB9 is the same as the $9F
nibble at offset $30BF. Those are the
same bits. That's the point at which,
pardon the pun, we've literally come
full circle.

Now let's copy the disk with a bit copy
program. I used EDD 4.4 for this test,
one of the most advanced bit copiers
ever developed.

                 --v--

TRACK: 22  START: 1800  LENGTH: 3DFF

24C0: FF+FF+FF+FF+FF+FF+FF+FF+
24C8: E9 BA DD DD+DD+DD+DD+DD+
24D0: DD+DD+DD+DD+DD+DD+DD+DD+
...
2A40: DD+DD+DD+DD+DD+DD+DD+DD+
2A48: FF 9F E7 F9 FE FE DB AD
2A50: D6 EB EB+EB+EB+EB+EB+EB+
2A58: EB+EB+EB+EB+EB+EB+EB+EB+
...
2C90: EB+EB+EB+EB+EB+EB+EB+EB+
2C98: FE+FF+FF+FF+FF+FF+FF+FF+
2CA0: FF+FF+FF+FF+FF+FF+FF+FF+
...
3B10: FF+FF+FF+FF+FF+FF+FF+FF+
3B18: FF+FF+FF+FF+FF+E9 BA DD
3B20: DD+DD+DD+DD+DD+DD+DD+DD+

                 --^--

$057E $DD nibbles -- exactly the same
as the original disk. (The acceptable
range was $0568..$059C.) And $0E84 $FF
nibbles -- a few more than the original
disk, but still within acceptable range
($0E68..$0E9C).

But what's all that in between? After
the $DD nibbles, we see the sequence
$FF $9F $E7 $F9 $FE, but then it goes
off into the weeds.  $FE $DB $AD $D6,
then a long sequence of... $EB?

Where did $EB come from?

And by the way, how can all these extra
nibbles fit on a track that is supposed
to be the same size as the original
disk?

In retrospect, that last question
points the way to the real answer, but
I could not see it at the time. For me,
the answer did not come from within the
Apple II, because, like so many copy
protection questions, the answer is not
directly visible from within the Apple
II. I had to jump out of the system.

With modern tools, we can now create
bit-perfect images of physical Apple II
floppy disks, then examine those images
on modern systems. Here is what I found
on my bit-perfect image of this 35-year
old floppy disk:

   /--DD--\  /--DD--\  /--DD--\
   110111010011011101001101110100 ...

Over and over and over and over. Those
are the $DD nibbles we saw earlier in
Copy II Plus, the ones that EDD 4 was
able to count and copy successfully...
or did it?

On the original disk, each $DD nibble
is followed by 2 "timing" (0) bits.
Since each valid nibble needs to start
with a "1" bit, those "0" bits between
nibbles are ignored. Even the copy
protection code ignores them. But that
doesn't mean they're useless.

Looking at the failed bit copy (again
from outside the system, via a disk
image that I could only examine on a
modern PC), those $DD nibbles look like
this:

   /--DD--\ /--DD--\ /--DD--\
   110111010110111010110111010 ...

Each $DD nibble is followed by only 1
"timing" (0) bit! They will still be
read as $DD nibbles; in fact, the copy
protection code successfully reads and
counts them. But the underlying bits on
the disk are very different. The
original disk had a 10-bit pattern; the
copy has a 9-bit pattern.

What's going on?

Disks spin independently from the Apple
II's CPU, which is very slow (1 Mhz).
There is barely enough time to read the
bits as they spin by the drive head,
and there is no way to slow down the
disk to read them more accurately. The
drive controller card (the thing in
slot 6) had to "help" by accumulating
the bits into an 8-bit value which
could be read by the main CPU.

Standard floppy disks were designed to
compensate for the limits of the
hardware; protected disks were designed
to exploit them. EDD 4 devised a clever
algorithm to detect the presence or
absence of timing bits after a nibble.
But it couldn't tell *how many* timing
bits are after any particular nibble:
1 or 2. There just wasn't enough time
to tell the difference before the next
bits started coming in.

EDD 4 isn't making a perfect copy of
this disk, because no Apple II program
could make a perfect copy of any disk.
It's making a reconstruction.

EDD 4 knows there is at least 1 timing
bit after each $FF nibble. It decides
to write out 2 timing bits after the
first four $FF nibbles, because $FF is
often used as a "self-synchronizing"
nibble value with the 10-bit pattern
1111111100 repeated four times. (See
p. 3-8 of "Beneath Apple DOS" for a
more detailed explanation of how this
works, and why four 10-bit nibbles is
sufficient to synchronize.) For the
rest of the $FF nibbles, EDD 4 guesses
1 timing bit, creating a 9-bit pattern
111111110. This is wrong, by the way;
the original disk had a 10-bit pattern
1111111100. But in the absence of
perfect information, EDD 4 decides that
it's better to drop bits and have too
few than to add bits and have too many.
If it guessed 2 timing bits where the
original had only 1, too often, it
could end up overwriting the start of
the track.

The original disk also used 2 timing
bits after each $DD nibble. This is an
unusual nibble value, so EDD 4 guesses,
incorrectly, that there is only one
timing bit after every $DD nibble. It
writes the 9-bit repeating pattern
110111010, which is different than the
original disk's 10-bit pattern of
1101110100.

Now EDD 4 has a problem: the track it's
reconstructed is too short, and it
doesn't know why. With the benefit of
hindsight and being able to jump out of
the system, we can see why: EDD 4 is
writing out 9-bit $DD nibbles instead
of 10-bit, and, with few exceptions,
9-bit $FF nibbles instead of 10-bit.

That's $057E + $0E80 bits short!

Then, like it always does, EDD 4 writes
out the track data again, from where it
ended the first time (more or less).
Now our copy has the wrong data twice,
part of which gets overwritten by the
wrong data from the first time and part
of which doesn't.

I believe the technical term for this
is "a complete mess."

Wait, it gets worse.

                   ~

               Chapter 4
     Now You See It, Now You Don't


There's only one thing you can put on a
disk that will change every time you
read it: nothing. And by "nothing," I
mean "a long sequence of zero bits."
And that's what is on the original disk
between each of these long groups of
nibbles: nothing.

A bit of background. When we say a
"zero bit," we really mean "the lack of
a magnetic state change." The Disk II
drive isn't digital; it's analog. If it
doesn't see a state change in a certain
period of time, it calls that a "0". If
it does see a change, it calls that a
"1". But the drive can only tolerate a
lack of state changes for so long --
about as long as it takes for two bits
to go by.

Fun fact(*): this is why you need to
use nibbles as an intermediate on-disk
format in the first place. No valid
nibble contains more than two zero bits
consecutively, when written from most-
significant to least-significant bit.

(*) not guaranteed, actual fun may vary

So what happens when a drive doesn't
see a state change after the equivalent
of two consecutive zero bits? The drive
thinks the disk is weak, and it starts
increasing the amplification to try to
compensate, looking for a valid signal.
But there is no signal. There is no
data. There is just a yawning abyss of
nothingness. Eventually, the drive gets
desperate and amplifies so much that it
starts returning random bits based on
ambient noise from the disk motor and
the magnetism of the Earth.

Seriously.

It's trivial to write zero bits to a
disk; just write a #$00 nibble to write
8 zero bits -- like any other 8-bit
nibble. You can write whatever you want
to a disk; it doesn't need to be what
DOS would consider a "valid" nibble.
But when you read that nibble back, the
drive can't handle 8 zero bits in a
row, so it will actually return some
random bits. Which is why no one does
that.

Returning random bits doesn't sound
very useful for a storage device, but
it's exactly what the developer wanted,
and that's exactly what this copy
protection scheme depends on. Here's
why:

Bit copiers can't duplicate a long
sequence of zero bits.

Why? Because that's not what they see.
What they see is some random bits --
the real zero bits interspersed with
phantom "1" bits. So that's what they
write to the target disk. Whatever
randomness they get when they read the
original disk will essentially get
"frozen" onto the copy.

As far as I can tell, the sequence of
10-bit $FF nibbles is followed by 12
extra zero bits, for a total of 14
after the final $FF nibble. (All others
have 2 zero bits.)

Here's what's on the disk between the
last half of the last $FF nibbles and
the first two $DD nibbles:

F--\              /--DD--\  /--DD--\
11110000000000000011011101001101110100
      ^^^^^^^^^^^^

More than two consecutive zero bits
will form an "abyss" that the floppy
drive will fill with randomness.  Some
of the zero bits in the abyss (shown
here above the "^^^^^^^^^^^" line) will
randomly transform into "1" bits. And
it will be a different set every time
you read the disk.

Seriously.

Here's one of many possible bitstreams
that might come out of the abyss:

F--\       /--E9--\/--BA--\ /--DD--\
11110000000111010011011101001101110100
      ^^^^^^^^^^^^

That's what I saw the first time I read
the original disk with the Copy II Plus
nibble editor: the abyss coalesces into
one full nibble ($E9). But if you look
closely, you'll see that the $E9 nibble
is stealing a bit from the first $DD
nibble. The number of $DD nibbles will
be one fewer this time, because the $E9
nibble swallowed the first one.

Now we're out of phase from the start
of the $DD nibbles, because the $E9
nibble stole a bit. After $E9, we see
a $BA nibble made up of bits 2-8 of
what ought to be the first $DD nibble,
plus one of the timing bits as its
least significant bit. Then we ignore
one timing bit after $BA, and now we're
back in phase, reading 10-bit $DD
nibbles again.

Then I read the original disk again and
got a completely different bitstream
between the last $FF and the first $DD.
It looked like this:

F--\  /--ED--\ /--9B--\/--A6--\/--E9--\
111100111011010100110111010011011101001
      ^^^^^^^^^^^^

/--BA--\ /--DD--\  /--DD--\  /--DD--\
101110100110111010011011101001101110100

Again, the random bits in the abyss are
interpreted as real bits, and they fool
the disk reading code into reading a
long sequence of out-of-phase nibbles,
$ED $9B $A6 $E9 $BA, before we finally
get back in phase and start reading
10-bit $DD nibbles again.

I say "finally" get back in phase, but
it really didn't take that long. No
matter how many bits get swallowed by
the abyss, the 10-bit $DD pattern will
always resynchronize. We'll always get
back in phase in time to find at least
$0570 $DD nibbles.

Now let's consider what happens on our
attempted copy. First of all, there is
no randomness, no abyss. Whatever
random bits it read from the original
disk, it writes those bits to the copy,
followed by the 9-bit $DD nibbles.

F--\ /--ED--\ /--9B--\/--AD--\/--D6--\
11110111011010100110111010110111010110
     ^^^^^^^^^^^^

/--EB--\ /--EB--\ /--EB--\ /--EB--\
111010110111010110111010110111010110

The initial sequence of out-of-phase
nibbles is different, between the
number of timing bits is different.
But we never get back to $DD. In fact,
we quickly reach a steady state where
we're reading out-of-phase $EB nibbles
over and over again.

The 9-bit $DD pattern will never
resynchronize itself. If you ever get
out of phase, you're going to stay out
of phase. Of course, you might not ever
get out of phase; it depends on which
bits come out of the abyss. But that's
where the $EB comes from: it's the
9-bit $DD, shifted by 3 bits.

Wait, it gets worse.

                   ~

               Chapter 5
 In Which Everything Is Designed To Be
   As Bad As Possible, And Succeeds


Track $22 on the original disk is split
up roughly 70/30, like this:

        1111111100         1101110100
|-----------------------|?|----------|?
       (10-bit $FF)       (10-bit $DD)

The first, longer section is full of
10-bit $FF nibbles. The second, shorter
section is full of 10-bit $DD nibbles.
The two "?" areas are the "weak" bits,
the abyss, which appear different every
time you read the disk and consume a
small number of the nibbles that follow
(but only a small number, because both
10-bit $FF and 10-bit $DD nibbles will
resynchronize).

The failed bit copy looks like this:

     111111110        110111010
|------------------|?|---------|?|/////
    (9-bit $FF)      (9-bit $DD)

The "/////" at the end of the track is
not modified (yet), because EDD 4 is
writing 9-bit nibbles instead of 10-bit
nibbles, so the track is shorter than
the original. But then EDD 4 writes the
data again, starting in the "/////"
region and wrapping around to overwrite
most (but not all) of the track it just
wrote:

     111111110        110111010   1101
|------------------|?|---------|?|----|
    (9-bit $FF)      (9-bit $DD)

That last section is detritus, leftover
9-bit $DD nibbles from the previous
write. Of course, these may also end up
out of phase, depending on how the bits
in the abyss come out. And as we've
seen, once a 9-bit $DD nibble gets out
of phase, it stays out of phase.

All of which explains what I initially
saw when I examined my failed bit copy
in the Copy II Plus nibble editor:

                 --v--

TRACK: 22  START: 1800  LENGTH: 3DFF

: FF+FF+FF+FF+FF+FF+FF+FF+
: E9 BA DD DD+DD+DD+DD+DD+ | 9-bit $DD
: DD+DD+DD+DD+DD+DD+DD+DD+ | nibbles
...
: DD+DD+DD+DD+DD+DD+DD+DD+
: FF 9F E7 F9 FE FE DB AD  | abyss
: D6 EB EB+EB+EB+EB+EB+EB+
: EB+EB+EB+EB+EB+EB+EB+EB+ | detritus
...
: EB+EB+EB+EB+EB+EB+EB+EB+
: FE+FF+FF+FF+FF+FF+FF+FF+ | 9-bit $FF
: FF+FF+FF+FF+FF+FF+FF+FF+ | nibbles
...
: FF+FF+FF+FF+FF+FF+FF+FF+
: FF+FF+FF+FF+FF+E9 BA DD  | abyss
: DD+DD+DD+DD+DD+DD+DD+DD+

                 --^--

Astute readers may complain that I've
oversimplified, and they would be
technically correct (the best kind of
correct). There's no guarantee that the
detritus is $DD nibbles; it could be
any part of the track, depending on
where the bit copier decides the track
starts and ends. There's no guarantee
that another bit copier would write the
track data twice. Other bit copiers
might make different guesses about the
number of timing bits. It appears that
one of the choices EDD 4 made -- adding
2 timing bits after the first few $FF
nibbles -- fixed the desynchronization
caused by the random bits after the $DD
nibbles. But this countermeasure was
not enough on its own.

This protection check is very strict.
It expects a track with a range of $DD
nibbles and a range of $FF nibbles and
very little else. To fool it, you'd
need to make a perfect bit copy. To do
that, you'd need to make a perfect bit
copier. No one ever did.

Quod erat liberandum.

---------------------------------------
A 4am crack                    No. 1735
------------------EOF------------------
